package gulimall;

import gulimall.config.ElasticSearchConfig;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.PipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.Avg;
import org.elasticsearch.search.aggregations.metrics.AvgAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.io.IOException;

/**
 * @author HLF
 * @date 2022/6/12 15:25
 */
@SpringBootTest
public class QueryTest1 {

    @Resource
    private RestHighLevelClient client;

    /**
     * 练习1：按照年龄聚合，并且求这些年龄段的这些人（每个分组）的平均薪资
     */
    @Test
    public void test01() throws IOException {
        SearchRequest searchRequest = new SearchRequest("bank");

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        sourceBuilder.size(0);//忽略其他字段

        //执行聚合
        sourceBuilder.aggregation(AggregationBuilders.terms("年龄分布").field("age")
                .subAggregation(AggregationBuilders.avg("平均薪资").field("balance"))//执行子聚合
        );

        searchRequest.source(sourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, ElasticSearchConfig.COMMON_OPTIONS);

        SearchHits hits = searchResponse.getHits();
        System.out.println("took:" + searchResponse.getTook());
        System.out.println("isTimeOut:" + searchResponse.isTimedOut());
        System.out.println("total:" + hits.getTotalHits());
        System.out.println("maxScore:" + hits.getMaxScore());

        Aggregations aggregations = searchResponse.getAggregations();
        Terms aggAge = aggregations.get("年龄分布");
        for (Terms.Bucket bucket : aggAge.getBuckets()) {
            String keyAsString = bucket.getKeyAsString();
            System.out.print("年龄分布：" + keyAsString + "，");
            System.out.print("个数：" + bucket.getDocCount() + "，");

            Aggregations bucketAggregations = bucket.getAggregations();
            Avg avgBalance = bucketAggregations.get("平均薪资");
            System.out.println("平均薪资：" + avgBalance.getValue());
        }
    }

    /**
     * 练习2：查出所有年龄分布，并且这些年龄段中M的平均薪资和 F 的平均薪资以及这个年龄段的总体平均薪资
     * TODO 实在是不会做，以后想办法实现
     */
    @Test
    @Deprecated
    public void test02() throws IOException {
        SearchRequest searchRequest = new SearchRequest("bank");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();


        /*//一级子聚合
        TermsAggregationBuilder builder1 = AggregationBuilders.terms("年龄分组").field("age");
        builder1.subAggregation(AggregationBuilders.avg("年龄分组平均薪资").field("balance"));


        //二级子聚合
        TermsAggregationBuilder builder2 = AggregationBuilders.terms("性别分组").field("gender");
        builder2.subAggregation(AggregationBuilders.avg("性别分组平均薪资").field("balance"));

        builder1.subAggregation(builder2);

        sourceBuilder.aggregation(builder1);*/

        //AggregationBuilders.terms("性别分组").field("gender")
        //                                .subAggregation(AggregationBuilders.avg("性别分组平均薪资").field("balance"))



        sourceBuilder.aggregation(AggregationBuilders.terms("年龄分组").field("age")
                .subAggregation(AggregationBuilders.avg("年龄分组平均薪资").field("balance"))
        );

        searchRequest.source(sourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, ElasticSearchConfig.COMMON_OPTIONS);

        SearchHits hits = searchResponse.getHits();
        System.out.println("took:" + searchResponse.getTook());
        System.out.println("isTimeOut:" + searchResponse.isTimedOut());
        System.out.println("total:" + hits.getTotalHits());
        System.out.println("maxScore:" + hits.getMaxScore());

        Aggregations aggregations = searchResponse.getAggregations();
        Terms aggAge = aggregations.get("年龄分组");
        if (aggAge != null) {
            for (Terms.Bucket bucket : aggAge.getBuckets()) {
                String keyAsString = bucket.getKeyAsString();
                System.out.print("年龄分布：" + keyAsString + "，");
                System.out.print("个数：" + bucket.getDocCount() + "，");

                Aggregations bucketAggregations = bucket.getAggregations();

                Avg avgBalance = bucketAggregations.get("年龄分组平均薪资");
                System.out.println("年龄分组平均薪资：" + avgBalance.getValue());

                Terms aggGender = bucketAggregations.get("性别分组");
                if (aggGender != null) {
                    for (Terms.Bucket aggGenderBucket : aggGender.getBuckets()) {
                        System.out.print("性别分布：" + aggGenderBucket.getKeyAsString());
                        System.out.println("性别：" + aggGenderBucket.getDocCount());

                        Aggregations aggGenderBucketAggregations = aggGenderBucket.getAggregations();
                        Avg genderAvgBalance = aggGenderBucketAggregations.get("balance");
                        System.out.println("性别分组平均薪资：" + genderAvgBalance.getValue());
                    }
                }
                System.out.println("=================================");
            }
        }

    }



    /**
     * 练习2：查出所有年龄分布，并且这些年龄段中M的平均薪资和 F 的平均薪资以及这些年龄段的总体平均薪资
     */
    @Test
    void test03() throws Exception {
        SearchRequest searchRequest = new SearchRequest("bank");

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        TermsAggregationBuilder ageGroup = AggregationBuilders.terms("年龄分布").field("age");
        ageGroup.subAggregation(AggregationBuilders.avg("年龄分布平均薪资").field("balance"));
        ageGroup.subAggregation(AggregationBuilders.terms("性别分组").field("gender.keyword")
                .subAggregation(AggregationBuilders.avg("性别分组平均薪资").field("balance"))
        );
        sourceBuilder.aggregation(ageGroup);

        searchRequest.source(sourceBuilder);

        SearchResponse response = client.search(searchRequest, ElasticSearchConfig.COMMON_OPTIONS);
        Aggregations aggregations = response.getAggregations();
        Terms ageTerms = aggregations.get("年龄分布");
        for (Terms.Bucket bucket : ageTerms.getBuckets()) {
            System.out.println("====年龄分布====");
            String keyAsString = bucket.getKeyAsString();
            System.out.print("年龄：" + keyAsString + ", ");
            System.out.print("个数：" + bucket.getDocCount() + ", ");

            Aggregations avgAgg = bucket.getAggregations();
            Avg ageAvg = avgAgg.get("年龄分布平均薪资");
            System.out.println("年龄分布平均薪资：" + ageAvg.getValue() + ", ");

            System.out.println("====性别分组====");
            Terms genderTerms = avgAgg.get("性别分组");
            for (Terms.Bucket genderBucket : genderTerms.getBuckets()) {
                String keyAsString1 = genderBucket.getKeyAsString();
                long docCount = genderBucket.getDocCount();

                System.out.print("性别：" + keyAsString1 + ", ");
                System.out.print("个数：" + docCount + ", ");

                Aggregations aggregations1 = genderBucket.getAggregations();
                Avg genderAvg = aggregations1.get("性别分组平均薪资");
                System.out.println("性别分组平均薪资：" + genderAvg.getValue());
            }

        }
    }
}
